﻿using Microsoft.Xna.Framework.Graphics;

namespace FxArchitect.Xna_3_1
{
    public struct SamplerStateBlock
    {
        const int ChangeCount = 10;
        const uint MaskAddressU = 1u << 0, MaskAddressV = 1u << 1, MaskAddressW = 1u << 2,
                   MaskMagFilter = 1u << 3, MaskMinFilter = 1u << 4, MaskMipFilter = 1u << 5,
                   MaskBorderColor = 1u << 6,
                   MaskMaxAnisotropy = 1u << 7, MaskMaxMipLevel = 1u << 8,
                   MaskMipMapLevelOfDetailBias = 1u << 9;

        #region Fields

        TextureAddressMode addressU, addressV, addressW;
        TextureFilter magFilter, minFilter, mipFilter;
        Color borderColor;
        int maxAnisotropy, maxMipLevel;
        float mipMapLevelOfDetailBias;
        uint changeMask;

        #endregion

        #region Properties

        public TextureAddressMode AddressU
        {
            get { return addressU; }
            set
            {
                changeMask |= (addressU != value) ? MaskAddressU : 0u;
                addressU = value;
            }
        }
        public TextureAddressMode AddressV
        {
            get { return addressV; }
            set
            {
                changeMask |= (addressV != value) ? MaskAddressV : 0u;
                addressV = value;
            }
        }
        public TextureAddressMode AddressW
        {
            get { return addressW; }
            set
            {
                changeMask |= (addressW != value) ? MaskAddressW : 0u;
                addressW = value;
            }
        }
        public TextureFilter MagFilter
        {
            get { return magFilter; }
            set
            {
                changeMask |= (magFilter != value) ? MaskMagFilter : 0u;
                magFilter = value;
            }
        }
        public TextureFilter MinFilter
        {
            get { return minFilter; }
            set
            {
                changeMask |= (minFilter != value) ? MaskMinFilter : 0u;
                minFilter = value;
            }
        }
        public TextureFilter MipFilter
        {
            get { return mipFilter; }
            set
            {
                changeMask |= (mipFilter != value) ? MaskMipFilter : 0u;
                mipFilter = value;
            }
        }
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                changeMask |= (borderColor != value) ? MaskBorderColor : 0u;
                borderColor = value;
            }
        }
        public int MaxAnisotropy
        {
            get { return maxAnisotropy; }
            set
            {
                changeMask |= (maxAnisotropy != value) ? MaskMaxAnisotropy : 0u;
                maxAnisotropy = value;
            }
        }
        public int MaxMipLevel
        {
            get { return maxMipLevel; }
            set
            {
                changeMask |= (maxMipLevel != value) ? MaskMaxMipLevel : 0u;
                maxMipLevel = value;
            }
        }
        public float MipMapLevelOfDetailBias
        {
            get { return mipMapLevelOfDetailBias; }
            set
            {
                changeMask |= (mipMapLevelOfDetailBias != value) ? MaskMipMapLevelOfDetailBias : 0u;
                mipMapLevelOfDetailBias = value;
            }
        }

        #endregion

        public void CaptureState(GraphicsDevice device, int samplerIndex)
        {
            addressU = device.SamplerStates[samplerIndex].AddressU;
            addressV = device.SamplerStates[samplerIndex].AddressV;
            addressW = device.SamplerStates[samplerIndex].AddressW;
            magFilter = device.SamplerStates[samplerIndex].MagFilter;
            minFilter = device.SamplerStates[samplerIndex].MinFilter;
            mipFilter = device.SamplerStates[samplerIndex].MipFilter;
            borderColor = device.SamplerStates[samplerIndex].BorderColor;
            maxAnisotropy = device.SamplerStates[samplerIndex].MaxAnisotropy;
            maxMipLevel = device.SamplerStates[samplerIndex].MaxMipLevel;
            mipMapLevelOfDetailBias = device.SamplerStates[samplerIndex].MipMapLevelOfDetailBias;
            changeMask = 0u;
        }
        public void ApplyState(GraphicsDevice device, int samplerIndex)
        {
            device.SamplerStates[samplerIndex].AddressU = addressU;
            device.SamplerStates[samplerIndex].AddressV = addressV;
            device.SamplerStates[samplerIndex].AddressW = addressW;
            device.SamplerStates[samplerIndex].MagFilter = magFilter;
            device.SamplerStates[samplerIndex].MinFilter = minFilter;
            device.SamplerStates[samplerIndex].MipFilter = mipFilter;
            device.SamplerStates[samplerIndex].BorderColor = borderColor;
            device.SamplerStates[samplerIndex].MaxAnisotropy = maxAnisotropy;
            device.SamplerStates[samplerIndex].MaxMipLevel = maxMipLevel;
            device.SamplerStates[samplerIndex].MipMapLevelOfDetailBias = mipMapLevelOfDetailBias;
        }
    }
}
